﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Configuration;
using SimpleLibrary;
using System.Data;
using System.IO;
using System.Threading;
using System.Collections.Concurrent;

namespace SimpleLoadGen
{
    
    class Program
    {
        private static bool bTimeout = false;
        private static System.Timers.Timer aTimer;

        static void Main(string[] args)
        {
           // Initialize Application
            Console.WriteLine("----- Initialize Configuration");
            SqlLoadGen.Init();

            Console.WriteLine("----- Initialize CSV Files");
            SqlLoadGen.InintCSVFiles();

            // Initilize variables
            int iMin = 0;
            int iMax = SqlLoadGen.mySqlTask[SqlLoadGen.mySqlTask.Count - 1].endRange;
            int iterator = int.MaxValue;
            int iRange = iterator / SqlLoadGen.numberOfWorker;

            // timer instance to stop loop 
            aTimer = new System.Timers.Timer(SqlLoadGen.timeOut * 1000);
            aTimer.Elapsed += aTimer_Elapsed;
            aTimer.Start();

            Console.WriteLine("----- Application is Running");

            Parallel.ForEach(Partitioner.Create(0, iterator, iRange),
                new ParallelOptions() { MaxDegreeOfParallelism = SqlLoadGen.numberOfWorker },
                () => new LocalData(),
                (range, loopState, localdata) =>
                {
                    // Initialize Local Data
                    if (localdata.myStatus == LocalStatus.None)
                    {
                        localdata.myValue = GetMyValue();
                        localdata.myStatus = LocalStatus.Started;
                        localdata.InitDatFilePointer();
                    }
                    
                    for (int i = range.Item1; i < range.Item2; i++)
                    {
                        int iTempRange = localdata.myRandom.Next(iMin, iMax);
                        SQLTask myTask = null;
                        
                        // choose task to execute
                        for (int x = 0; x < SqlLoadGen.mySqlTask.Count; x++)
                        {
                            if (iTempRange >= SqlLoadGen.mySqlTask[x].startRange &&
                                iTempRange < SqlLoadGen.mySqlTask[x].endRange)
                            {
                                myTask = SqlLoadGen.mySqlTask[x].CopyTask();
                                break;
                            }
                        }
                        DataAccess dataAccess = new DataAccess();
                        dataAccess.ExecuteMyTask(myTask, localdata);

                        // when we hit timeout then stop the parallel loop
                        if (bTimeout)
                        {
                            loopState.Stop();
                            return localdata;
                        }

                    }
                    return localdata;
                },
            _ => { });

            Console.WriteLine(" ");
            Console.WriteLine("----- Generating Report");
            DateTime mydate = DateTime.Now;
            QueryStatistics.GenerateReport(mydate);
            ExceptionStatistics.GenerateReport(mydate);
            Console.Read();
        }

        static void aTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            bTimeout = true;
            aTimer.Stop();
        }
               

        #region GetMyvalue
        private static Object thisLock = new Object();
        private static int thisNumber = 0;
        public static int GetMyValue()
        {
            lock (thisLock)
            {
                thisNumber = thisNumber + 1;
                return thisNumber;
            }
        }
        #endregion
    }
}
